package me.fung.wubi.base.define.value

import java.util.ArrayList

data class Code(
    val value: String
) : Comparable<Code> {
    val length get() = value.length

    init {
        assert(value.length < 5)
    }

    fun subCodes(): List<Code> {
        val result = ArrayList<Code>()
        for (i in 1..length) {
            value.substring(0..i).also { result.add(Code(it)) }
        }
        return result
    }

    override fun compareTo(other: Code): Int {
        if (value == other.value) return 0
        val maxLen = if (length > other.length) length else other.length
        for (i in 0 until maxLen) {
            val c1 = charOrNull(i)
            val c2 = other.charOrNull(i)
            if (c1 == null) return -1
            if (c2 == null) return 1
            val result = c1.compareTo(c2)
            if (result != 0) return result
        }
        return 0
    }

    private fun charOrNull(index: Int): Char? {
        return value.getOrNull(index)
    }

    fun hasShortCode(): Boolean {
        return value.length > 1
    }

    fun shortCode(): Code? {
        if (!hasShortCode()) return null
        return Code(value.substring(0, length - 1))
    }

    fun shortCodes(includeSelf: Boolean = true): List<Code> {
        val list = ArrayList<Code>()
        if (includeSelf) list.add(this)
        var c: Code? = shortCode()
        while (c != null) {
            list.add(c)
            c = c.shortCode()
        }
        list.reverse()
        return list
    }

    companion object {
        val Null: Code = Code("")
    }
}